Skip to content

fix(messages): skip map-related legacy fallback for mower devices#1565

Merged
edenhaus merged 7 commits into
DeebotUniverse:devfrom
Beennnn:fix/skip-maptrace-legacy-for-mower
May 7, 2026
Merged

fix(messages): skip map-related legacy fallback for mower devices#1565
edenhaus merged 7 commits into
DeebotUniverse:devfrom
Beennnn:fix/skip-maptrace-legacy-for-mower

Conversation

@Beennnn

@Beennnn Beennnn commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Summary

When a mower (Ecovacs GOAT G1, A1600 RTK, A3000 LiDAR Pro, …) is mowing, its firmware pushes spontaneous onMapTrace MQTT messages. They flow through messages.get_message() which falls back via _LEGACY_USE_GET_COMMAND to GetMapTrace, whose parser does not support the on-wire format used by recent mower firmware (observed: 1.15.13). The parse fails inside _handle_error_or_analyse and emits a WARNING per push.

In one user setup this produced 217 520 Could not parse getMapTrace warnings over 3 days (~70k/day, ~50/min during mowing), bloating the HA homeassistant.log and the recorder DB by ~100 MB.

Mowers do not expose a map= capability in their hardware definitions (see 0jbd6s, 2ap5uq, 2i0fns, 5xu9h3, aadham, xmp9ds, itk04l), so even if the legacy fallback succeeded, the parsed map-trace data would have nowhere to land. The fallback is pure noise on these devices.

Change

Add an optional device_type: DeviceType | None = None argument to get_message and get_legacy_message. When the device is a MOWER, map-related legacy messages are skipped silently before reaching the parser:

_MAP_LEGACY_COMMANDS = frozenset({
    "getCachedMapInfo", "getMapSet", "getMapSubSet",
    "getMapTrace", "getMinorMap", "getMultiMapState",
})

Vacuums (DeviceType.VACUUM) and callers without a specified type (None) fall through unchanged — fully backwards compatible.

Device._handle_message reads device_type defensively via getattr so existing tests mocking Capabilities with spec_set= (which excludes dataclass field names from dir()) continue to work — they fall back to the no-filter path.

Refs

Test plan

  • test_get_messages (existing 7 cases) — pass unchanged
  • test_get_messages_device_type_filter (10 new cases) — verify mowers skip map-related legacy fallbacks while non-map messages and other device types remain unaffected
  • Full suite: 707/707 tests pass, no regression
  • Real-world: user reports back after deploying a custom HACS build (will follow up in Disable getMapTrace() for Ecovacs Goat Lawn Mower #1376 once HACS release ships this change)

When a mower (e.g. Ecovacs GOAT G1, A1600 RTK, A3000 LiDAR Pro) is
mowing, its firmware pushes spontaneous `onMapTrace` MQTT messages.
They flow through `messages.get_message()` which falls back via
`_LEGACY_USE_GET_COMMAND` to `GetMapTrace`, whose parser does not
support the on-wire format used by recent mower firmware
(observed: 1.15.13). The parse fails inside
`_handle_error_or_analyse` and emits a WARNING per push.

In one user setup this produced 217 520 `Could not parse getMapTrace`
warnings over 3 days (~70 k/day, ~50/min during mowing), bloating the
HA `homeassistant.log` and the recorder DB by ~100 MB.

Mowers do not expose a `map=` capability in their hardware
definitions, so successfully parsed map-trace data would have nowhere
to land anyway — the fallback is pure noise on these devices.

This adds an optional `device_type` argument to `get_message` and
`get_legacy_message`. When the device is a `MOWER`, map-related
legacy messages (`onMapTrace`, `onMapSet`, `onMapSubSet`,
`onMinorMap`, `onCachedMapInfo`, `onMultiMapState` and their
`get/off/report` variants) are skipped silently before reaching the
parser. Vacuums and devices with no specified type fall through
unchanged.

`Device._handle_message` reads `device_type` defensively via `getattr`
so existing test mocks that don't expose the dataclass field on
`spec_set=Capabilities` continue to work — they fall back to the
no-filter path.

Tests:

- `test_get_messages` (existing 7 cases) — pass unchanged.
- `test_get_messages_device_type_filter` (10 new cases) — verify
  mowers skip map-related legacy fallbacks while non-map messages
  and other device types remain unaffected.
- Full suite: 707/707 pass, no regression.

Refs: DeebotUniverse#1376 (Disable getMapTrace for Goat)
Refs: DeebotUniverse#852 (GOAT A1600 RTK Support)
Comment thread deebot_client/messages/json/__init__.py Outdated
Comment thread deebot_client/messages/json/__init__.py Outdated
Address review feedback on DeebotUniverse#1565:
- Drop the explanatory comment block above ``_MAP_LEGACY_COMMANDS``
- Replace the ``device_type == DeviceType.MOWER`` check with a
  capability-based one. ``get_message`` now takes ``has_map: bool``
  (keyword-only) and ``get_legacy_message`` skips map-related fallbacks
  when the device does not expose a ``map`` capability — independent of
  whether the device is a mower, vacuum, or future device class.
- ``Device._handle_message`` derives ``has_map`` from
  ``capabilities.map`` via ``getattr`` so test mocks unaffected.
reniko pushed a commit to reniko/client.py that referenced this pull request May 1, 2026
GetMapTrace V2 format is better handled by upstream PRs DeebotUniverse#1565 and
DeebotUniverse#1567. The xmp9ds test duplicates existing coverage per maintainer
feedback on DeebotUniverse#1564.

https://claude.ai/code/session_01YFYjxwixRZrtjfv1aUfoVQ
Comment thread deebot_client/device.py Outdated
Comment thread deebot_client/device.py Outdated
Beennnn and others added 5 commits May 6, 2026 00:32
Address review feedback from edenhaus:
- Pass the whole `static: StaticDeviceInfo` object to `get_message()`
  instead of extracting `data_type` and `has_map` separately at the
  call site.
- Remove `getattr` in device.py — access `capabilities.map` directly
  since the attribute is defined on the dataclass.
- Remove `lru_cache` on `get_message` since `StaticDeviceInfo` contains
  non-trivially-hashable `Capabilities` objects. The function is cheap
  enough without caching (string lookups + one regex).
- Update tests to use real `StaticDeviceInfo` fixtures (yna5xi with map,
  xmp9ds without map) instead of passing primitive params.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented May 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.81818% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.99%. Comparing base (8980d8c) to head (d357220).
⚠️ Report is 11 commits behind head on dev.

Files with missing lines Patch % Lines
deebot_client/device.py 0.00% 0 Missing and 1 partial ⚠️
deebot_client/messages/__init__.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1565      +/-   ##
==========================================
+ Coverage   94.92%   94.99%   +0.06%     
==========================================
  Files         156      158       +2     
  Lines        6105     6189      +84     
  Branches      350      351       +1     
==========================================
+ Hits         5795     5879      +84     
  Misses        248      248              
  Partials       62       62              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented May 7, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 113 untouched benchmarks


Comparing Beennnn:fix/skip-maptrace-legacy-for-mower (d357220) with dev (7266b58)

Open in CodSpeed

@edenhaus edenhaus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Beennnn 👍

Did some small changes :)

@edenhaus edenhaus added the pr: bugfix PR, which fixes a bug label May 7, 2026
@edenhaus edenhaus merged commit 332b86e into DeebotUniverse:dev May 7, 2026
24 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: bugfix PR, which fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Disable getMapTrace() for Ecovacs Goat Lawn Mower

2 participants